package com.gl.buscaminas.buscaminasRestService;

import java.net.URI;

import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import com.gl.buscaminas.BuscaminasJuego;
import com.gl.buscaminas.FabricaBuscaminasJuego;
import com.gl.buscaminas.excepciones.BuscaminasNoEncontradoException;
import com.gl.buscaminas.excepciones.BuscaminasOperacionInvalidaException;
import com.gl.buscaminas.excepciones.BuscaminasParametroNuloException;

/**
 * 
 * @author Omar Moreno 04/03/2012
 * 
 */
@Path("/buscaminas")
public class BuscaminasServicioREST {

	private FabricaBuscaminasJuego fabricaBuscaminas;
	@Context
	UriInfo uriInfo;

	public BuscaminasServicioREST() {
		this.fabricaBuscaminas = FabricaBuscaminasJuego.getInstancia();
	}

	private Buscaminas construirBuscaminasDTO(BuscaminasJuego juego,
			String idJuego) throws BuscaminasOperacionInvalidaException {
		Buscaminas buscaminas = new Buscaminas();
		buscaminas.setId(idJuego);
		buscaminas.setEstadoJuego(juego.obtenerEstadoJuego());
		buscaminas.setEstadoTablero(juego.obtenerEstadoTablero());
		UriBuilder ub = uriInfo.getBaseUriBuilder();
		URI userUri = ub.path("buscaminas").path(idJuego).build();
		buscaminas.setLink(userUri);
		return buscaminas;
	}

	@GET
	@Produces({ MediaType.TEXT_PLAIN })
	public String bienvenido() {
		return "Bienvenido a Buscaminas";
	}

	@GET
	@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	public Juegos obtenerJuegos() throws BuscaminasNoEncontradoException,
			BuscaminasOperacionInvalidaException {
		Juegos juegos = new Juegos();
		for (String idJuego : this.fabricaBuscaminas.recuperarJuegosClaves()) {
			BuscaminasJuego juego = this.fabricaBuscaminas
					.recuperarJuego(idJuego);
			Buscaminas buscaminas = construirBuscaminasDTO(juego, idJuego);
			juegos.agregarJuego(buscaminas);
		}
		return juegos;
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public Buscaminas crearTablero(
			@DefaultValue("4") @QueryParam("filas") Integer filas,
			@DefaultValue("4") @QueryParam("columnas") Integer columnas,
			@Context UriInfo uriInfo) throws BuscaminasNoEncontradoException,
			BuscaminasParametroNuloException,
			BuscaminasOperacionInvalidaException {
		String idJuego = this.fabricaBuscaminas.crearJuego(filas, columnas);
		Buscaminas buscaminas = construirBuscaminasDTO(
				this.fabricaBuscaminas.recuperarJuego(idJuego), idJuego);
		return buscaminas;
	}

	@PUT
	@Path("{id}/casilleros")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Buscaminas ponerBomba(@PathParam("id") String id,
			@FormParam("fila") Integer fila,
			@FormParam("columna") Integer columna, @Context UriInfo uriInfo)
			throws BuscaminasNoEncontradoException,
			BuscaminasOperacionInvalidaException,
			BuscaminasParametroNuloException {
		BuscaminasJuego juego = this.fabricaBuscaminas.recuperarJuego(id);
		juego.ponerBomba(fila, columna);
		Buscaminas buscaminas = construirBuscaminasDTO(
				this.fabricaBuscaminas.recuperarJuego(id), id);
		return buscaminas;
	}

	@PUT
	@Path("{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Buscaminas comenzarJuego(@PathParam("id") String id)
			throws BuscaminasNoEncontradoException,
			BuscaminasOperacionInvalidaException {
		BuscaminasJuego juego = this.fabricaBuscaminas.recuperarJuego(id);
		juego.comenzarJuego();
		Buscaminas buscaminas = construirBuscaminasDTO(
				this.fabricaBuscaminas.recuperarJuego(id), id);
		return buscaminas;
	}

	@POST
	@Path("{id}/casilleros")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Buscaminas destapar(@PathParam("id") String id,
			@FormParam("fila") Integer fila,
			@FormParam("columna") Integer columna)
			throws BuscaminasNoEncontradoException,
			BuscaminasOperacionInvalidaException {
		BuscaminasJuego juego = this.fabricaBuscaminas.recuperarJuego(id);
		juego.destapar(fila, columna);
		Buscaminas buscaminas = construirBuscaminasDTO(
				this.fabricaBuscaminas.recuperarJuego(id), id);
		return buscaminas;
	}

	@GET
	@Path("{id}")
	@Produces(MediaType.APPLICATION_JSON)
	public Buscaminas obtenerEstadoJuego(@PathParam("id") String id)
			throws BuscaminasNoEncontradoException,
			BuscaminasOperacionInvalidaException {
		Buscaminas buscaminas = construirBuscaminasDTO(
				this.fabricaBuscaminas.recuperarJuego(id), id);
		return buscaminas;
	}
}
